<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">
        <!-- 添加一个自定义事件 -->
        <my-header @addTodo="addTodo" />
        <!-- 
        向孙子组件（my-item）组件传递属性，最简单的方法需要先向该组件(my-item)的父组件(my-list)传递属性，
      然后在通过父组件传到下面的子组件中 
      -->
        <!-- <my-list :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo" /> -->
        <my-list :todos="todos" />
        <!-- 父组件传递自定义事件给子组件，是为了让子组件传递数据给父组件 ，-->
        <my-footer
          :todos="todos"
          @checkAllTodo="checkAllTodo"
          @clearAllTodo="clearAllTodo"
        />
      </div>
    </div>
  </div>
</template>

<script>
import MyHeader from "./components/MyHeader.vue";
import MyFooter from "./components/MyFooter.vue";
import MyList from "./components/MyList.vue";

import pubsub from "pubsub-js";

export default {
  name: "App",
  components: { MyHeader, MyFooter, MyList },
  data() {
    return {
      // 在最后添加一个默认值 [], 修复调用length错误
      todos: JSON.parse(localStorage.getItem("todos")) || [],
    };
  },
  mounted() {
    // 全局事件总线
    // 第二步：接收数据的组件要先绑定全局总线事件
    this.$bus.$on("checkTodo", this.checkTodo);
    this.$bus.$on("updateTodo", this.updateTodo);

    // this.$bus.$on("deleteTodo", this.deleteTodo);
    // 使用发布订阅来实现
    // const pid = pubsub.subscribe("deleteTodo", (msgName, data) => {
    //   this.deleteTodo(data);
    // });
    this.pubId = pubsub.subscribe("deleteTodo", this.deleteTodo);
  },
  // 第三步：使用完绑定的事件后，解绑该事件，减少占用
  beforeDestroy() {
    this.$bus.$off("checkTodo");
    // 绑定后，也必须设置解绑
    this.$bus.$off("updateTodo");
    // this.$bus.$off("deleteTodo");
    pubsub.unsubscribe(this.pubId);
  },
  methods: {
    // 注意不要和props、data,computed的属性名称相同
    addTodo(obj) {
      this.todos.unshift(obj);
    },
    // 取消勾选
    checkTodo(id) {
      this.todos.forEach((element) => {
        if (element.id == id) {
          element.done = !element.done;
        }
      });
    },

    // 删除一个todo
    deleteTodo(id) {
      console.log("deleteTodo1");
      this.todos = this.todos.filter((item) => {
        return item.id !== id;
      });
    },

    //deleteTodo 函数被覆盖
    deleteTodo(_, id) {
      console.log("deleteTodo2");
      this.todos = this.todos.filter((item) => {
        return item.id !== id;
      });
    },

    // 全选或取消全选
    checkAllTodo(value) {
      if (value) {
        this.todos.forEach((element) => {
          element.done = true;
        });
      } else {
        this.todos.forEach((element) => {
          element.done = false;
        });
      }
    },
    // 清除所有已完成的todo
    clearAllTodo() {
      this.todos = this.todos.filter((item) => {
        return !item.done;
      });
    },

    // 更新一个todo
    updateTodo(id, title) {
      this.todos.forEach((element) => {
        if (element.id == id) {
          element.title = title;
        }
      });
    },
  },
  watch: {
    todos: {
      // 打开深度监视,使用完整版语法，配置deep:true，才能监视对象内部的变化
      deep: true,
      handler(value) {
        localStorage.setItem("todos", JSON.stringify(value));
      },
    },
  },
};
</script>

<style>
/** basic */
body {
  background: #fff;
}
.btn {
  display: inline-block;
  padding: 4px 12px;
  margin-bottom: 0;
  font-size: 14px;
  line-height: 20px;
  text-align: center;
  vertical-align: middle;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 1px 2px rgba(0, 0, 0, 0.5);
  border-radius: 4px;
}
.btn-danger {
  color: #fff;
  background-color: #da4f49;
  border: 1px solid #bd362f;
}
.btn-danger:hover {
  color: #fff;
  background-color: #bd362f;
}
.btn-edit {
  color: #fff;
  background-color: #0d66b3;
  border: 1px solid #b1413b;
}
.btn:focus {
  outline: none;
}
.todo-container {
  width: 600px;
  margin: 0 auto;
}
.todo-container .todo-wrap {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
}
</style>
